#!/bin/bash
#-------------------------------------------------------------------------------
# Copyright (c) 2018 by Ando Ki (andoki@gmail.com)
#-------------------------------------------------------------------------------
# gen_apb_top.sh -- Top-level generator for AMBA APB system
#-------------------------------------------------------------------------------
# VERSION: 2018.07.19.
#-------------------------------------------------------------------------------
SHELL=/bin/bash

#-------------------------------------------------------------------------------
TYP_MST=ahb
NUM_SLV=2
NUM_BYTES=1024
NAME_BUS=
FILE_OUT="top.v"
BIT_AXI_ADDR=32
BIT_AXI_DATA=32

#-------------------------------------------------------------------------------
function func_help() {
   echo "Usage : $0 [options]"
   echo "      -axi|ahb           :AXI-to-APB or AHB-to-APB, \"ahb\""
   echo "      -axiad  bits       :AXI address width, ${BIT_AXI_ADDR}"
   echo "      -axida  bits       :AXI data width, ${BIT_AXI_DATA}"
   echo "      -slv    num        :num of slaves, i.e., memories, ${NUM_SLV}"
   echo "      -siz    bytes      :size of each slave in bytes, ${NUM_BYTES}"
   echo "      -bus    module     :name of bus, ${NAME_BUS}"
   echo "      -out    file_name  :output file name, ${FILE_OUT}"
   echo "      -h/-?              :printf help"
   echo ""
   echo    "Example: $ $0 -ahb -slv 2 -siz 1024 -out top.v"
   return 0
}

#-------------------------------------------------------------------------------
while [ "`echo $1|cut -c1`" = "-" ]; do
  case $1 in
      -ahb) TYP_MST=ahb
            ;;
      -axi) TYP_MST=axi
            ;;
      -axiad) shift
            if [ ! "$1" ]; then
               echo "-axiad needs option"
               func_help
               exit -1
            fi
            BIT_AXI_ADDR=$1
            ;;
      -axida) shift
            if [ ! "$1" ]; then
               echo "-axida needs option"
               func_help
               exit -1
            fi
            BIT_AXI_DATA=$1
            ;;
      -slv) shift
            if [ ! "$1" ]; then
               echo "-slv needs option"
               func_help
               exit -1
            fi
            NUM_SLV=$1
            ;;
      -siz) shift
            if [ ! "$1" ]; then
               echo "-siz needs option"
               func_help
               exit -1
            fi
            NUM_BYTES=$1
            ;;
      -out) shift
            if [ ! "$1" ]; then
               echo "-out needs option"
               func_help
               exit -1
            fi
            FILE_OUT=$1
            ;;
      -h|-\?) func_help
              exit -1
              ;;
      *)      echo "Unknown option: $1"
              func_help
              exit -1
              ;;
  esac
  shift
done
if [ ! -z "$1" ]; then
   echo un-known options: $1
   exit 1
fi

#-------------------------------------------------------------------------------
function func_ahb() {
cat << EOT
//------------------------------------------------------------------------------
// top.v generated by "gen_apb_top.sh"
//------------------------------------------------------------------------------
\`timescale 1ns/1ns
\`ifndef CLK_FREQ
\`define CLK_FREQ       50000000
\`endif
\`ifndef BUS_DELAY
\`define BUS_DELAY #(1)
\`endif
\`ifndef MEM_DELAY
\`define MEM_DELAY 0
\`endif
\`ifndef SIZE_IN_BYTES
\`define SIZE_IN_BYTES $NUM_BYTES
\`endif

module top;
   //---------------------------------------------------------------------------
   localparam NUM_SLV=${NUM_SLV};
   //---------------------------------------------------------------------------
EOT
   cnt_slv=0;
   startX=0;
   sizeX=`echo "ibase=10;obase=16;${NUM_BYTES}"|bc`
   while [ ${cnt_slv} -lt ${NUM_SLV} ]; do
       startX=`echo "ibase=10;obase=16;$[${cnt_slv}*${NUM_BYTES}]"|bc`
echo "   localparam  P_PSEL${cnt_slv}_START=32'h${startX},P_PSEL${cnt_slv}_SIZE=32'h${sizeX};"
       cnt_slv=$[${cnt_slv}+1]
   done
cat << EOT
   //---------------------------------------------------------------------------
   localparam CLK_PERIOD_HALF=1_000_000_000/(\`CLK_FREQ*2);
   reg         HCLK   = 1'b0; always #(CLK_PERIOD_HALF) HCLK=~HCLK;
   reg         HRESETn= 1'b0; initial #155 HRESETn=1'b1;
   //---------------------------------------------------------------------------
   wire        PCLK   = HCLK;
   wire        PRESETn= HRESETn;
   //---------------------------------------------------------------------------
   wire [31:0]        \`BUS_DELAY HADDR ;
   wire [ 3:0]        \`BUS_DELAY HPROT ;
   wire               \`BUS_DELAY HLOCK ;
   wire [ 1:0]        \`BUS_DELAY HTRANS;
   wire               \`BUS_DELAY HWRITE;
   wire [ 2:0]        \`BUS_DELAY HSIZE ;
   wire [ 2:0]        \`BUS_DELAY HBURST;
   wire [31:0]        \`BUS_DELAY HWDATA;
   wire [31:0]        \`BUS_DELAY HRDATA;
   wire [ 1:0]        \`BUS_DELAY HRESP ;
   wire               \`BUS_DELAY HREADY;
   //---------------------------------------------------------------------------
   wire               \`BUS_DELAY S_PENABLE;
   wire [31:0]        \`BUS_DELAY S_PADDR  ;
   wire               \`BUS_DELAY S_PWRITE ;
   wire [31:0]        \`BUS_DELAY S_PWDATA ;
   wire [31:0]        \`BUS_DELAY S_PRDATA [0:NUM_SLV-1];
   wire [NUM_SLV-1:0] \`BUS_DELAY S_PSEL   ;
   \`ifdef AMBA_APB3
   wire [NUM_SLV-1:0] \`BUS_DELAY S_PREADY ;
   wire [NUM_SLV-1:0] \`BUS_DELAY S_PSLVERR;
   \`endif
   \`ifdef AMBA_APB4
   wire [ 2:0]        \`BUS_DELAY S_PPROT  ;
   wire [ 3:0]        \`BUS_DELAY S_PSTRB  ;
   \`endif
   //---------------------------------------------------------------------------
   ${NAME_BUS} #(.P_NUM(NUM_SLV) // num of slaves
EOT
   cnt_slv=0;
   while [ ${cnt_slv} -lt ${NUM_SLV} ]; do
echo "                  ,.P_PSEL${cnt_slv}_START(P_PSEL${cnt_slv}_START),.P_PSEL${cnt_slv}_SIZE(P_PSEL${cnt_slv}_SIZE)"
       cnt_slv=$[${cnt_slv}+1]
   done
echo "                  ,.CLOCK_RATIO   ( 2'b0        ) // 0=1:1, 3=async"
echo "                  )"
echo "   u_ahb2apb ("
echo "        .HRESETn       ( HRESETn    )"
echo "      , .HCLK          ( HCLK       )"
echo "      , .HSEL          ( HTRANS[1]  )"
echo "      , .HADDR         ( HADDR      )"
echo "      , .HTRANS        ( HTRANS     )"
echo "      , .HSIZE         ( HSIZE      )"
echo "      , .HBURST        ( HBURST     )"
echo "      , .HPROT         ( HPROT      )"
echo "      , .HLOCK         ( HLOCK      )"
echo "      , .HWRITE        ( HWRITE     )"
echo "      , .HWDATA        ( HWDATA     )"
echo "      , .HRDATA        ( HRDATA     )"
echo "      , .HRESP         ( HRESP      )"
echo "      , .HREADYin      ( HREADY     )"
echo "      , .HREADYout     ( HREADY     )"
echo "      , .PRESETn       ( PRESETn    )"
echo "      , .PCLK          ( PCLK       )"
echo "      , .S_PENABLE     ( S_PENABLE  )"
echo "      , .S_PADDR       ( S_PADDR    )"
echo "      , .S_PWRITE      ( S_PWRITE   )"
echo "      , .S_PWDATA      ( S_PWDATA   )"
   cnt_slv=0;
   while [ ${cnt_slv} -lt ${NUM_SLV} ]; do
echo "      , .S${cnt_slv}_PSEL       ( S_PSEL   [${cnt_slv}] )"
echo "      , .S${cnt_slv}_PRDATA     ( S_PRDATA [${cnt_slv}] )"
echo "      \`ifdef AMBA_APB3"
echo "      , .S${cnt_slv}_PREADY     ( S_PREADY [${cnt_slv}] )"
echo "      , .S${cnt_slv}_PSLVERR    ( S_PSLVERR[${cnt_slv}] )"
echo "      \`endif"
       cnt_slv=$[${cnt_slv}+1]
   done
echo "      \`ifdef AMBA_APB4"
echo "      , .S_PPROT       ( S_PPROT    )"
echo "      , .S_PSTRB       ( S_PSTRB    )"
echo "      \`endif"
echo "   );"
cat << EOT
   //---------------------------------------------------------------------------
   wire done;
   //---------------------------------------------------------------------------
   ahb_tester #(.P_MST_ID(0)
               ,.P_NUM_MST(1)
               ,.P_NUM_SLV(NUM_SLV)
               ,.P_SIZE_IN_BYTES(\`SIZE_IN_BYTES))
   u_tester (
         .HRESETn ( HRESETn )
       , .HCLK    ( HCLK    )
       , .HBUSREQ (         )
       , .HGRANT  ( 1'b1    )
       , .HADDR   ( HADDR   )
       , .HPROT   ( HPROT   )
       , .HLOCK   ( HLOCK   )
       , .HTRANS  ( HTRANS  )
       , .HWRITE  ( HWRITE  )
       , .HSIZE   ( HSIZE   )
       , .HBURST  ( HBURST  )
       , .HWDATA  ( HWDATA  )
       , .HRDATA  ( HRDATA  )
       , .HRESP   ( HRESP   )
       , .HREADY  ( HREADY  )
   );
   assign done = u_tester.done;
   //---------------------------------------------------------------------------
   generate
   genvar idy;
   for (idy=0; idy<NUM_SLV; idy=idy+1) begin : BLK_SLV
        mem_apb #(.P_SLV_ID(idy)
                 ,.P_SIZE_IN_BYTES(\`SIZE_IN_BYTES)
                 ,.P_DELAY(\`MEM_DELAY))
        u_mem_apb (
              .PRESETn   ( PRESETn        )
            , .PCLK      ( PCLK           )
            , .PSEL      ( S_PSEL   [idy] )
            , .PENABLE   ( S_PENABLE      )
            , .PADDR     ( S_PADDR        )
            , .PWRITE    ( S_PWRITE       )
            , .PWDATA    ( S_PWDATA       )
            , .PRDATA    ( S_PRDATA [idy] )
            \`ifdef AMBA_APB3
            , .PREADY    ( S_PREADY [idy] )
            , .PSLVERR   ( S_PSLVERR[idy] )
            \`endif
            \`ifdef AMBA_APB4
            , .PPROT     ( S_PPROT        )
            , .PSTRB     ( S_PSTRB        )
            \`endif
        );
   end // for
   endgenerate
   //---------------------------------------------------------------------------
   initial begin
       wait(HRESETn==1'b0);
       wait(HRESETn==1'b1);
       wait(done==1'b1);
       repeat (5) @ (posedge HCLK);
       \$finish(2);
   end
   //---------------------------------------------------------------------------
   initial begin
      \`ifdef VCD
          // use +define+VCD in 'vlog'
          \$dumpfile("wave.vcd");
          \$dumpvars(0);
      \`else
           // use +VCD in 'vsim'
           if (\$test\$plusargs("VCD")) begin
               \$dumpfile("wave.vcd");
               \$dumpvars(5);
           end
      \`endif
   end
endmodule
EOT
}

#-------------------------------------------------------------------------------
function log2 {
    local x=0
    for (( y=$1-1 ; $y > 0; y >>= 1 )) ; do
        let x=$x+1
    done
    echo $x
}

#-------------------------------------------------------------------------------
function func_axi() {
cat << EOT
//------------------------------------------------------------------------------
// top.v generated by "gen_apb_top.sh"
//------------------------------------------------------------------------------
\`timescale 1ns/1ns
\`ifndef CLK_FREQ
\`define CLK_FREQ       50000000
\`endif
\`ifdef __ICARUS__
\`define BUS_DELAY
\`else
\`ifndef BUS_DELAY
\`define BUS_DELAY #(1)
\`endif
\`endif
\`ifndef MEM_DELAY
\`define MEM_DELAY 0
\`endif
\`ifndef SIZE_IN_BYTES
\`define SIZE_IN_BYTES $NUM_BYTES
\`endif
EOT

echo "\`define AMBA_AXI4"
echo "\`ifdef AMBA_AXI4"
echo "\`define AMBA_QOS"
echo "\`else"
echo "\`undef AMBA_QOS"
echo "\`endif"

cat << EOT
module top;
   //---------------------------------------------------------------------------
   localparam NUM_SLV=${NUM_SLV};
   localparam MST_ID      = 1;
   localparam WIDTH_CID   = 4    // Channel ID width in bits
            , WIDTH_ID    = 4    // ID width in bits
            , WIDTH_AD    =$BIT_AXI_ADDR    // address width
            , WIDTH_DA    =$BIT_AXI_DATA    // data width
            , WIDTH_DS    =(WIDTH_DA/8)  // data strobe width
            , WIDTH_SID   =WIDTH_CID+WIDTH_ID // ID for slave
            , WIDTH_AWUSER=0  // Write-address user path
            , WIDTH_WUSER =0  // Write-data user path
            , WIDTH_BUSER =0  // Write-response user path
            , WIDTH_ARUSER=0  // read-address user path
            , WIDTH_RUSER =0; // read-data user path
   localparam WIDTH_PAD =32
            , WIDTH_PDA =32;
   //---------------------------------------------------------------------------
EOT
   cnt_slv=0;
   startX=0;
   lengX=$(log2 ${NUM_BYTES})
   sizeX=`echo "ibase=10;obase=16;${lengX}"|bc`
   while [ ${cnt_slv} -lt ${NUM_SLV} ]; do
       startX=`echo "ibase=10;obase=16;$[${cnt_slv}*${NUM_BYTES}]"|bc`
echo "   localparam  ADDR_PBASE${cnt_slv}=32'h${startX},ADDR_PLENGTH${cnt_slv}=32'h${sizeX};"
       cnt_slv=$[${cnt_slv}+1]
   done
cat << EOT
   //---------------------------------------------------------------------------
   localparam CLK_PERIOD_HALF=1_000_000_000/(\`CLK_FREQ*2);
   reg         ACLK   = 1'b0; always #(CLK_PERIOD_HALF) ACLK=~ACLK;
   reg         ARESETn= 1'b0; initial #155 ARESETn=1'b1;
   //---------------------------------------------------------------------------
   wire        PCLK = ACLK;
   wire        PRESETn = ARESETn;
   //---------------------------------------------------------------------------
   wire  [WIDTH_SID-1:0]    \`BUS_DELAY AWID       ; assign AWID[WIDTH_SID-1:WIDTH_CID] = MST_ID;
   wire  [WIDTH_AD-1:0]     \`BUS_DELAY AWADDR     ;
   \`ifdef AMBA_AXI4
   wire  [ 7:0]             \`BUS_DELAY AWLEN      ;
   wire                     \`BUS_DELAY AWLOCK     ;
   \`else
   wire  [ 3:0]             \`BUS_DELAY AWLEN      ;
   wire  [ 1:0]             \`BUS_DELAY AWLOCK     ;
   \`endif
   wire  [ 2:0]             \`BUS_DELAY AWSIZE     ;
   wire  [ 1:0]             \`BUS_DELAY AWBURST    ;
   \`ifdef AMBA_AXI_CACHE
   wire  [ 3:0]             \`BUS_DELAY AWCACHE    ;
   \`endif
   \`ifdef AMBA_AXI_PROT
   wire  [ 2:0]             \`BUS_DELAY AWPROT     ;
   \`endif
   wire                     \`BUS_DELAY AWVALID    ;
   wire                     \`BUS_DELAY AWREADY    ;
   \`ifdef AMBA_QOS
   wire  [ 3:0]             \`BUS_DELAY AWQOS      ;
   wire  [ 3:0]             \`BUS_DELAY AWREGION   ;
   \`endif
   \`ifdef AMBA_AXI_AWUSER
   wire  [WIDTH_AWUSER-1:0] \`BUS_DELAY AWUSER     ;
   \`endif
   \`ifndef AMBA_AXI4
   wire  [WIDTH_SID-1:0]    \`BUS_DELAY WID        ; assign WID[WIDTH_SID-1:WIDTH_CID] = MST_ID;
   \`endif
   wire  [WIDTH_DA-1:0]     \`BUS_DELAY WDATA      ;
   wire  [WIDTH_DS-1:0]     \`BUS_DELAY WSTRB      ;
   wire                     \`BUS_DELAY WLAST      ;
   wire                     \`BUS_DELAY WVALID     ;
   wire                     \`BUS_DELAY WREADY     ;
   \`ifdef AMBA_AXI_WUSER
   wire  [WIDTH_WUSER-1:0]  \`BUS_DELAY WUSER      ;
   \`endif
   wire  [WIDTH_SID-1:0]    \`BUS_DELAY BID        ; assign BID[WIDTH_SID-1:WIDTH_CID] = MST_ID;
   wire  [ 1:0]             \`BUS_DELAY BRESP      ;
   wire                     \`BUS_DELAY BVALID     ;
   wire                     \`BUS_DELAY BREADY     ;
   \`ifdef AMBA_AXI_BUSER
   wire  [WIDTH_BUSER-1:0]  \`BUS_DELAY BUSER      ;
   \`endif
   wire  [WIDTH_SID-1:0]    \`BUS_DELAY ARID       ; assign ARID[WIDTH_SID-1:WIDTH_CID] = MST_ID;
   wire  [WIDTH_AD-1:0]     \`BUS_DELAY ARADDR     ;
   \`ifdef AMBA_AXI4
   wire  [ 7:0]             \`BUS_DELAY ARLEN      ;
   wire                     \`BUS_DELAY ARLOCK     ;
   \`else
   wire  [ 3:0]             \`BUS_DELAY ARLEN      ;
   wire  [ 1:0]             \`BUS_DELAY ARLOCK     ;
   \`endif
   wire  [ 2:0]             \`BUS_DELAY ARSIZE     ;
   wire  [ 1:0]             \`BUS_DELAY ARBURST    ;
   \`ifdef AMBA_AXI_CACHE
   wire  [ 3:0]             \`BUS_DELAY ARCACHE    ;
   \`endif
   \`ifdef AMBA_AXI_PROT
   wire  [ 2:0]             \`BUS_DELAY ARPROT     ;
   \`endif
   wire                     \`BUS_DELAY ARVALID    ;
   wire                     \`BUS_DELAY ARREADY    ;
   \`ifdef AMBA_QOS
   wire  [ 3:0]             \`BUS_DELAY ARQOS      ;
   wire  [ 3:0]             \`BUS_DELAY ARREGION   ;
   \`endif
   \`ifdef AMBA_AXI_ARUSER
   wire  [WIDTH_ARUSER-1:0] \`BUS_DELAY ARUSER     ;
   \`endif
   wire  [WIDTH_SID-1:0]    \`BUS_DELAY RID        ; assign RID[WIDTH_SID-1:WIDTH_CID] = MST_ID;
   wire  [WIDTH_DA-1:0]     \`BUS_DELAY RDATA      ;
   wire  [ 1:0]             \`BUS_DELAY RRESP      ;
   wire                     \`BUS_DELAY RLAST      ;
   wire                     \`BUS_DELAY RVALID     ;
   wire                     \`BUS_DELAY RREADY     ;
   \`ifdef AMBA_AXI_RUSER
   wire  [WIDTH_RUSER-1:0]  \`BUS_DELAY RUSER      ;
   \`endif
   wire                     \`BUS_DELAY CSYSREQ    ;
   wire                     \`BUS_DELAY CSYSACK    ;
   wire                     \`BUS_DELAY CACTIVE    ;
   //------------------------------------------------------------------------
   wire               \`BUS_DELAY S_PENABLE;
   wire [31:0]        \`BUS_DELAY S_PADDR  ;
   wire               \`BUS_DELAY S_PWRITE ;
   wire [31:0]        \`BUS_DELAY S_PWDATA ;
   wire [31:0]        \`BUS_DELAY S_PRDATA [0:NUM_SLV-1];
   wire [NUM_SLV-1:0] \`BUS_DELAY S_PSEL   ;
   \`ifdef AMBA_APB3
   wire [NUM_SLV-1:0] \`BUS_DELAY S_PREADY ;
   wire [NUM_SLV-1:0] \`BUS_DELAY S_PSLVERR;
   \`endif
   \`ifdef AMBA_APB4
   wire [ 2:0]        \`BUS_DELAY S_PPROT  ;
   wire [ 3:0]        \`BUS_DELAY S_PSTRB  ;
   \`endif
   //---------------------------------------------------------------------------
   ${NAME_BUS} #(.NUM_PSLAVE(NUM_SLV) // num of slaves
               ,.AXI_WIDTH_SID (WIDTH_SID)
               ,.AXI_WIDTH_AD  (WIDTH_AD )
               ,.AXI_WIDTH_DA  (WIDTH_DA )
               ,.WIDTH_PAD     (WIDTH_PAD)
               ,.WIDTH_PDA     (WIDTH_PDA)
EOT
   cnt_slv=0;
   while [ ${cnt_slv} -lt ${NUM_SLV} ]; do
echo "                  ,.ADDR_PBASE${cnt_slv}(ADDR_PBASE${cnt_slv}),.ADDR_PLENGTH${cnt_slv}(ADDR_PLENGTH${cnt_slv})"
       cnt_slv=$[${cnt_slv}+1]
   done
echo "                  , .CLOCK_RATIO   ( 2'b0       ) // 0=1:1, 3=async"
echo "                  )"
echo "   u_axi2apb ("
echo "       .ARESETn            (ARESETn)"
echo "     , .ACLK               (ACLK   )"
echo "     , .AWID               (AWID   [WIDTH_SID-1:0])"
echo "     , .AWADDR             (AWADDR )"
echo "     , .AWLEN              (AWLEN  )"
echo "     , .AWLOCK             (AWLOCK )"
echo "     , .AWSIZE             (AWSIZE )"
echo "     , .AWBURST            (AWBURST)"
echo "     \`ifdef AMBA_AXI_CACHE"
echo "     , .AWCACHE            (AWCACHE)"
echo "     \`endif"
echo "     \`ifdef AMBA_AXI_PROT"
echo "     , .AWPROT             (AWPROT )"
echo "     \`endif"
echo "     , .AWVALID            (AWVALID)"
echo "     , .AWREADY            (AWREADY)"
echo "     \`ifdef AMBA_QOS"
echo "     , .AWQOS              (AWQOS   )"
echo "     , .AWREGION           (AWREGION)"
echo "     \`endif"
echo "     \`ifndef AMBA_AXI4"
echo "     , .WID                (WID   [WIDTH_SID-1:0])"
echo "     \`endif"
echo "     , .WDATA              (WDATA )"
echo "     , .WSTRB              (WSTRB )"
echo "     , .WLAST              (WLAST )"
echo "     , .WVALID             (WVALID)"
echo "     , .WREADY             (WREADY)"
echo "     , .BID                (BID   [WIDTH_SID-1:0])"
echo "     , .BRESP              (BRESP )"
echo "     , .BVALID             (BVALID)"
echo "     , .BREADY             (BREADY)"
echo "     , .ARID               (ARID  [WIDTH_SID-1:0])"
echo "     , .ARADDR             (ARADDR)"
echo "     , .ARLEN              (ARLEN )"
echo "     , .ARLOCK             (ARLOCK)"
echo "     , .ARSIZE             (ARSIZE )"
echo "     , .ARBURST            (ARBURST)"
echo "     \`ifdef AMBA_AXI_CACHE"
echo "     , .ARCACHE            (ARCACHE)"
echo "     \`endif"
echo "     \`ifdef AMBA_AXI_PROT"
echo "     , .ARPROT             (ARPROT )"
echo "     \`endif"
echo "     , .ARVALID            (ARVALID)"
echo "     , .ARREADY            (ARREADY)"
echo "     \`ifdef AMBA_QOS"
echo "     , .ARQOS              (ARQOS   )"
echo "     , .ARREGION           (ARREGION)"
echo "     \`endif"
echo "     , .RID                (RID    [WIDTH_SID-1:0])"
echo "     , .RDATA              (RDATA  )"
echo "     , .RRESP              (RRESP  )"
echo "     , .RLAST              (RLAST  )"
echo "     , .RVALID             (RVALID )"
echo "     , .RREADY             (RREADY )"
echo "      , .PRESETn       ( PRESETn    )"
echo "      , .PCLK          ( PCLK       )"
echo "      , .S_PENABLE     ( S_PENABLE  )"
echo "      , .S_PADDR       ( S_PADDR    )"
echo "      , .S_PWRITE      ( S_PWRITE   )"
echo "      , .S_PWDATA      ( S_PWDATA   )"
   cnt_slv=0;
   while [ ${cnt_slv} -lt ${NUM_SLV} ]; do
echo "      , .S${cnt_slv}_PSEL       ( S_PSEL   [${cnt_slv}] )"
echo "      , .S${cnt_slv}_PRDATA     ( S_PRDATA [${cnt_slv}] )"
echo "      \`ifdef AMBA_APB3"
echo "      , .S${cnt_slv}_PREADY     ( S_PREADY [${cnt_slv}] )"
echo "      , .S${cnt_slv}_PSLVERR    ( S_PSLVERR[${cnt_slv}] )"
echo "      \`endif"
       cnt_slv=$[${cnt_slv}+1]
   done
echo "      \`ifdef AMBA_APB4"
echo "      , .S_PPROT       ( S_PPROT    )"
echo "      , .S_PSTRB       ( S_PSTRB    )"
echo "      \`endif"
echo "   );"
cat << EOT
   //---------------------------------------------------------------------------
   wire done;
   //---------------------------------------------------------------------------
   axi_tester #(.P_MST_ID(0)
               ,.P_NUM_SLV(NUM_SLV)
               ,.P_SIZE_IN_BYTES(\`SIZE_IN_BYTES)
               ,.WIDTH_ID (WIDTH_ID ) // ID width in bits
               ,.WIDTH_AD (WIDTH_AD ) // address width
               ,.WIDTH_DA (WIDTH_DA ))// data width
   u_tester (
         .ARESETn   (ARESETn      )
       , .ACLK      (ACLK         )
       , .AWID      ( AWID         [WIDTH_ID-1:0])
       , .AWADDR    ( AWADDR       )
       , .AWLEN     ( AWLEN        )
       , .AWLOCK    ( AWLOCK       )
       , .AWSIZE    ( AWSIZE       )
       , .AWBURST   ( AWBURST      )
       \`ifdef AMBA_AXI_CACHE
       , .AWCACHE   ( AWCACHE      )
       \`endif
       \`ifdef AMBA_AXI_PROT
       , .AWPROT    ( AWPROT       )
       \`endif
       , .AWVALID   ( AWVALID      )
       , .AWREADY   ( AWREADY      )
       \`ifdef AMBA_QOS
       , .AWQOS     ( AWQOS        )
       , .AWREGION  ( AWREGION     )
       \`endif
       \`ifndef AMBA_AXI4
       , .WID       ( WID          [WIDTH_ID-1:0])
       \`endif
       , .WDATA     ( WDATA        )
       , .WSTRB     ( WSTRB        )
       , .WLAST     ( WLAST        )
       , .WVALID    ( WVALID       )
       , .WREADY    ( WREADY       )
       , .BID       ( BID          [WIDTH_ID-1:0])
       , .BRESP     ( BRESP        )
       , .BVALID    ( BVALID       )
       , .BREADY    ( BREADY       )
       , .ARID      ( ARID         [WIDTH_ID-1:0])
       , .ARADDR    ( ARADDR       )
       , .ARLEN     ( ARLEN        )
       , .ARLOCK    ( ARLOCK       )
       , .ARSIZE    ( ARSIZE       )
       , .ARBURST   ( ARBURST      )
       \`ifdef AMBA_AXI_CACHE
       , .ARCACHE   ( ARCACHE      )
       \`endif
       \`ifdef AMBA_AXI_PROT
       , .ARPROT    ( ARPROT       )
       \`endif
       , .ARVALID   ( ARVALID      )
       , .ARREADY   ( ARREADY      )
       \`ifdef AMBA_QOS
       , .ARQOS     ( ARQOS        )
       , .ARREGION  ( ARREGION     )
       \`endif
       , .RID       ( RID          [WIDTH_ID-1:0])
       , .RDATA     ( RDATA        )
       , .RRESP     ( RRESP        )
       , .RLAST     ( RLAST        )
       , .RVALID    ( RVALID       )
       , .RREADY    ( RREADY       )
       , .CSYSREQ   ( CSYSREQ      )
       , .CSYSACK   ( CSYSACK      )
       , .CACTIVE   ( CACTIVE      )
   );
   assign CSYSREQ = 1'b0;
   assign done = u_tester.done;
   //---------------------------------------------------------------------------
   generate
   genvar idy;
   for (idy=0; idy<NUM_SLV; idy=idy+1) begin : BLK_SLV
        mem_apb #(.P_SLV_ID(idy)
                 ,.P_SIZE_IN_BYTES(\`SIZE_IN_BYTES)
                 ,.P_DELAY(\`MEM_DELAY))
        u_mem_apb (
              .PRESETn   ( PRESETn        )
            , .PCLK      ( PCLK           )
            , .PSEL      ( S_PSEL   [idy] )
            , .PENABLE   ( S_PENABLE      )
            , .PADDR     ( S_PADDR        )
            , .PWRITE    ( S_PWRITE       )
            , .PWDATA    ( S_PWDATA       )
            , .PRDATA    ( S_PRDATA [idy] )
            \`ifdef AMBA_APB3
            , .PREADY    ( S_PREADY [idy] )
            , .PSLVERR   ( S_PSLVERR[idy] )
            \`endif
            \`ifdef AMBA_APB4
            , .PPROT     ( S_PPROT        )
            , .PSTRB     ( S_PSTRB        )
            \`endif
        );
   end // for
   endgenerate
   //---------------------------------------------------------------------------
   initial begin
       wait(ARESETn==1'b0);
       wait(ARESETn==1'b1);
       wait(done==1'b1);
       repeat (5) @ (posedge ACLK);
       \$finish(2);
   end
   //---------------------------------------------------------------------------
   initial begin
      \`ifdef VCD
          // use +define+VCD in 'vlog'
          \$dumpfile("wave.vcd");
          \$dumpvars(0);
      \`else
           // use +VCD in 'vsim'
           if (\$test\$plusargs("VCD")) begin
               \$dumpfile("wave.vcd");
               \$dumpvars(5);
           end
      \`endif
   end
endmodule
EOT
}

#-------------------------------------------------------------------------------
NAME_BUS="${TYP_MST}_to_apb_s${NUM_SLV}"
#-------------------------------------------------------------------------------
set -o errexit

if [ ${TYP_MST} == "ahb" ]; then
     exec 3>&1 1>$FILE_OUT
     func_ahb;
     exec 1>&3 3>&-
elif [ ${TYP_MST} == "axi" ]; then
     exec 3>&1 1>$FILE_OUT
     func_axi;
     exec 1>&3 3>&-
else
     echo "ERROR ${TYP_MST} not known"
fi

#-------------------------------------------------------------------------------
# Revision history:
#
# 2018.07.19: Started by Ando Ki (adki@future-ds.com)
#-------------------------------------------------------------------------------
